﻿using agsXMPP;
using agsXMPP.protocol.component;
using agsXMPP.Xml.Dom;
using RH.EBS.Core.Configuration;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Text;
using agsXMPP.protocol;
using agsXMPP.protocol.client;

namespace RH.EBS.Core.XMPP
{
    public class XmppHelper
    {
        public XmppClientConnection xmppConn = new XmppClientConnection();
        private static readonly string ofServer = ConfigurationManager.AppSettings["ofServer"];


        #region 属性
        /// <summary>
        /// Openfire服务器地址
        /// </summary>
        public string OpenfireServer
        {
            get
            {
                if (string.IsNullOrEmpty(ofServer))
                { throw new ArgumentNullException("请配置openfire服务器地址"); }
                return !ofServer.EndsWith("/") ? ofServer + "/" : ofServer;
            }
        }
        //  System.Uri uri = new System.Uri(OpenfireServer);

        /// <summary>
        /// UserService服务器地址
        /// </summary>
        public string UserService { get { return OpenfireServer + "plugins/userService/userservice"; } }

        /// <summary>
        /// 返回信息
        /// UserAlreadyExistsException	A user with the same name as the user about to be added, already exists. For ‘add_roster’ operation, roster item with the same JID already exists.
        /// RequestNotAuthorised	The supplied secret does not match the secret specified in the Admin Console or the requester is not a valid IP address.
        /// UserServiceDisabled	The User Service is currently set to disabled in the Admin Console.
        /// SharedGroupException	Roster item can not be added/deleted to/from a shared group for operations with roster.
        /// </summary>
        public string ResultMessage { get; set; }

        public bool IsLogined { get; set; }
        #endregion

        #region 用户维护

        public string AccessServer(XmppUserEntity user)
        {
            try
            {
                using (WebClient client = new WebClient())
                {
                    string url = UserService + user.ToString();
                    System.Uri postForm = new System.Uri(url);
                    ResultMessage = client.DownloadString(postForm);
                }
            }
            catch (Exception ex)
            {
                Loger.WriteLog(ex);
            }


            return ResultMessage;
        }

        /// <summary>
        /// 注册用户
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public bool Register(XmppUserEntity user)
        {
            user.OpType = "add";
            bool result = false;
            result = AccessServer(user).Contains("<result>ok");
            return result;
        }

        public bool Update(XmppUserEntity user)
        {
            user.OpType = "update";
            return AccessServer(user).Contains("<result>ok");
        }
        public bool Delete(XmppUserEntity user)
        {
            user.OpType = "delete";
            return AccessServer(user).Contains("<result>ok");
        }
        public bool Enable(XmppUserEntity user)
        {
            user.OpType = "enable";
            return AccessServer(user).Contains("<result>ok");
        }
        public bool Disable(XmppUserEntity user)
        {
            user.OpType = "disable";
            return AccessServer(user).Contains("<result>ok");
        }
        #endregion

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="pwd"></param>
        /// <returns></returns>
        /// 
        public bool Login(string userName, string pwd)
        {
            // bool result = false;
            System.Uri uri = new System.Uri(OpenfireServer);

            Jid jid = new Jid(string.Format("{0}@{1}", userName, uri.Host));

            xmppConn.Password = pwd;
            xmppConn.Username = jid.User;
            xmppConn.Server = jid.Server;
            //xmppConn.Port = 5222;
            //xmppConn.AutoAgents = false;
            //xmppConn.AutoPresence = true;
            //xmppConn.RegisterAccount = false;
            //xmppConn.AutoRoster = true;
            //xmppConn.AutoResolveConnectServer = true;
            try
            {
                xmppConn.OnRosterStart += OnRosterStart;
                xmppConn.OnRosterItem += OnRosterItem;
                xmppConn.OnRosterEnd += OnRosterEnd;
                xmppConn.OnPresence += OnPresence;
                xmppConn.OnMessage += OnMessage;
                // xmppConn.OnRosterStart += new ObjectHandler(xmppCon_OnRosterStart);
                // xmppConn.OnRosterItem += new XmppClientConnection.RosterHandler(xmppCon_OnRosterItem);
                // xmppConn.OnRosterEnd += new ObjectHandler(xmppCon_OnRosterEnd);
                // xmppConn.OnPresence += new agsXMPP.protocol.client.PresenceHandler(xmppCon_OnPresence);
                //xmppConn.OnMessage += new agsXMPP.protocol.client.MessageHandler(OnMessage);

                xmppConn.OnLogin += new ObjectHandler(OnLogin);
                xmppConn.Open();
            }
            catch (Exception ex)
            {
                Loger.WriteLog(ex);
            }
            // return result;
            return IsLogined;
        }

        void xmppConn_OnMessage(object sender, agsXMPP.protocol.client.Message msg)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 广播
        /// </summary>
        /// <param name="Context">广播内容</param>
        /// <param name="messageType">消息类型</param>
        public void BrocastMsg(string Context, MessageType messageType = MessageType.chat)
        {
            System.Uri uri = new System.Uri(OpenfireServer);
            xmppConn.Send(new agsXMPP.protocol.client.Message(new Jid("all@broadcast." + uri.Host + ""), messageType, Context));
        }

        /// <summary>
        /// 群(组)发
        /// </summary>
        /// <param name="GropName">组名</param>
        /// <param name="Context">发送内容</param>
        /// <param name="messageType">消息类型</param>
        public void SendMsgToGroup(string GropName, string Context, MessageType messageType = MessageType.chat)
        {
            System.Uri uri = new System.Uri(OpenfireServer);
            xmppConn.Send(new agsXMPP.protocol.client.Message(new Jid(GropName + "@broadcast." + uri.Host + ""), messageType, Context));
        }

        /// <summary>
        /// 点对点发
        /// </summary>
        /// <param name="ReseiveUser">接收人</param>
        /// <param name="Context">发送内容</param>
        /// <param name="messageType">消息类别</param>
        public void SendMsgToSomeBoy(string ReseiveUser, string Context, MessageType messageType = MessageType.chat)
        {
            System.Uri uri = new System.Uri(OpenfireServer);
            xmppConn.Send(new agsXMPP.protocol.client.Message(new Jid(ReseiveUser + "@" + uri.Host), messageType, Context));
        }

        public event ObjectHandler OnRosterStart;
        public event agsXMPP.XmppClientConnection.RosterHandler OnRosterItem;
        public event ObjectHandler OnRosterEnd;
        public event agsXMPP.protocol.client.PresenceHandler OnPresence;
        public event agsXMPP.protocol.client.MessageHandler OnMessage;
        public event ObjectHandler OnLogin;

        #region Test Code
        void xmppCon_OnLogin(object sender)
        {
            //Console.WriteLine();
            // PrintEvent("Logged in to server");

            IsLogined = true;
        }
        void xmppCon_OnMessage(object sender, agsXMPP.protocol.client.Message msg)
        {

            if (msg.Body != null)
            {

                //PrintEvent(String.Format("Got message from: {0}", msg.From.ToString()));
                //PrintEvent("message: " + msg.Body);
                //MessageBox.Show(msg.Body.ToString());
                // PrintInfo("");
                // IncomingMessage(msg);
            }
        }
        static void xmppCon_OnPresence(object sender, agsXMPP.protocol.client.Presence pres)
        {
            //PrintInfo(String.Format("Got presence from: {0}", pres.From.ToString()));
            //PrintInfo(String.Format("type: {0}", pres.Type.ToString()));
            //PrintInfo(String.Format("status: {0}", pres.Status));
            //PrintInfo("");
        }
        static void xmppCon_OnRosterItem(object sender, agsXMPP.protocol.iq.roster.RosterItem item)
        {
            // PrintInfo(String.Format("Got contact: {0}", item.Jid));
            // MessageBox.Show(item.Jid.ToString());
        }
        static void xmppCon_OnRosterEnd(object sender)
        {
            //_bWait = false;
            //Console.WriteLine();
            //PrintInfo("All contacts received");
        }
        //static void xmppCon_OnPresence(object sender, Presence pres)
        //{
        //    //PrintInfo(String.Format("Got presence from: {0}", pres.From.ToString()));
        //    //PrintInfo(String.Format("type: {0}", pres.Type.ToString()));
        //    //PrintInfo(String.Format("status: {0}", pres.Status));
        //    //PrintInfo("");
        //}



        //void xmppCon_OnMessage(object sender, agsXMPP.protocol.client.Message msg)
        //{

        //    if (msg.Body != null)
        //    {

        //      //  PrintEvent(String.Format("Got message from: {0}", msg.From.ToString()));
        //      //  PrintEvent("message: " + msg.Body);
        //      //  MessageBox.Show(msg.Body.ToString());
        //        // PrintInfo("");
        //        // IncomingMessage(msg);
        //    }
        //}

        static void xmppCon_OnRosterStart(object sender)
        {
            //  PrintEvent("Getting contacts now");

        }
        #endregion

    }
    public class XmppUserEntity
    {
        #region Sample
        //The following example adds a user        
        //http://example.com:9090/plugins/userService/userservice?type=add&secret=bigsecret&username=kafka&password=drowssap&name=franz&email=franz@kafka.com

        //The following example adds a user, adds two shared groups (if not existing) and adds the user to both groups.
        //http://example.com:9090/plugins/userService/userservice?type=add&secret=bigsecret&username=kafka&password=drowssap&name=franz&email=franz@kafka.com&groups=support,finance

        //The following example deletes a user and all roster items of the user.
        //http://example.com:9090/plugins/userService/userservice?type=delete&secret=bigsecret&username=kafka

        //The following example disables a user (lockout)
        //http://example.com:9090/plugins/userService/userservice?type=disable&secret=bigsecret&username=kafka

        //The following example enables a user (removes lockout)
        //http://example.com:9090/plugins/userService/userservice?type=enable&secret=bigsecret&username=kafka

        //The following example updates a user
        //http://example.com:9090/plugins/userService/userservice?type=update&secret=bigsecret&username=kafka&password=drowssap&name=franz&email=beetle@kafka.com

        //The following example adds new roster item with subscription ‘both’ for user ‘kafka’
        //http://example.com:9090/plugins/userService/userservice?type=add_roster&secret=bigsecret&username=kafka&item_jid=franz@example.com&name=franz&subscription=3

        //The following example adds new roster item with subscription ‘both’ for user ‘kafka’ and adds kafka to roster groups ‘family’ and ‘friends’
        //http://example.com:9090/plugins/userService/userservice?type=add_roster&secret=bigsecret&username=kafka&item_jid=franz@example.com&name=franz&subscription=3&groups=family,friends

        //The following example updates existing roster item to subscription ‘none’ for user ‘kafka’
        //http://example.com:9090/plugins/userService/userservice?type=update_roster&secret=bigsecret&username=kafka&item_jid=franz@example.com&name=franz&subscription=0

        //The following example deletes a specific roster item ‘franz@kafka.com’ for user ‘kafka’
        //http://example.com:9090/plugins/userService/userservice?type=delete_roster&secret=bigsecret&username=kafka&item_jid=franz@example.com

        //The following example gets all groups
        //http://example.com:9090/plugins/userService/userservice?type=grouplist&secret=bigsecret 
        //Which replies an XML group list formatted like this:
        //<result>
        //    <groupname>group1</groupname>
        //    <groupname>group2</groupname>
        //</result>

        //The following example gets all groups for a specific user
        //http://example.com:9090/plugins/userService/userservice?type=usergrouplist&secret=bigsecret&username=kafka 
        //Which replies an XML group list formatted like this:
        //<result>
        //    <groupname>usergroup1</groupname>
        //    <groupname>usergroup2</groupname>
        //</result>
        //* When sending double characters (Chinese/Japanese/Korean etc) you should URLEncode the string as utf8. 
        //In Java this is done like this 
        //URLEncoder.encode(username, “UTF-8”)); 
        //If the strings are encoded incorrectly, double byte characters will look garbeled in the Admin Console.   
        #endregion

        /// <summary>
        /// add/delete/update/add_roster/update_roster/delete_roster/usergrouplist/disable/enable
        /// </summary>
        public string OpType { get; set; }

        private static readonly string ofSecret = ConfigurationManager.AppSettings["ofSecret"];
        public string Secret
        {
            get
            {
                if (string.IsNullOrEmpty(ofSecret)) throw new ArgumentNullException("请配置openfire Secret验证key。");
                return ofSecret;
            }
        }
        public string Username { get; set; }
        public string Password { get; set; }
        public string RealName { get; set; }
        public string Email { get; set; }

        public string Groups { get; set; }

        public override string ToString()
        {
            string postStr = "?type={0}&secret={1}&username={2}&password={3}&name={4}&email={5}&groups={6}";
            string result = string.Format(postStr, OpType, Secret, Username, Password, RealName, Email, Groups);
            return result;
        }

    }
}
